很久没有更新 Blog 了。但这并不代表生活索然无味,最近的一段时间,
- MSRA 总算办夏令营了!于是有幸到在北京玩了六天,见到了许多新老朋友,有许多事情可以说。但如果篇幅有限,只能用一个字来总结这次夏令营,那只能是“热”
- 实现了 Linux 下的一个通用的 Sandbox,新版本 ZOJ 的后端应该就是它了。同时,发现了现有 ZOJ 几个非常严重的 Bug,真不知道在开源的情况下 ZOJ 是怎么活到现在的,现在想想还是冷汗直流啊
- 与学校免试研究生相关事情总算告于段落了,结果是和朋友们一起还要在学校呆至少两年多。可以向后来的学弟学妹们传达的信息是,如果不想被直博,那么就趁早准备出国吧…
- 做了一些简单的对各种 Web Sever 的性能测试,发现 Thin 表现出色,之前对用 ROR 性能的担忧就减少许多了。新版本的 ZOJ 的前端实现应该就是用它了
- 跟踪了东方永夜抄并实现了有一些功能的外挂,虽然即便这样,尝试了几次也只能让最高分的最高位达到 4 ,即将到 5,相比之下最高的未作弊记录是 6 …
- 用 LaTeX 和一段 Ruby 脚本自动实现集训队的代码模版的排版,相比之前手工用 Word 来排版,就不会出现少一个右括号而导致的悲剧情况了
这些事情有的是属于另外一个大一点的事情的一部分,完成度还没有到一定程度;有的是通过 Google around 再自己调一调就能完成的事情;有的是不适合公开的事情,所以就没有写
那么回到正题,Rainlendar 是一个很好的桌面日历软件,官方非常厚道,未注册的话只会在网络日历事件的工具提示中显示“[UNREGISTERED]”,没有使用时间限制和其他功能限制。而且,只要为 Rainlendar 的翻译做出一点贡献就能免费获得一份授权。
可惜目前中文版的翻译进度是 100%,而授权费用要 100 人名币多,翻一倍再凭借学生证就能买到 Windows 7 正版了,太贵了 那么来自己和谐掉这个“[UNREGISTERED]”吧。
显然,下面的途径都能达到目的:
- 和谐掉授权检测部分的代码,让未授权始终通过;进一步地查明授权文件验证方式,算出授权文件
- 找出并和谐加入“[UNREGISTERED]”字样部分的代码
- 找到“[UNREGISTERED]”所在的数据段(如果存在),将这个字符串修改成空串
- 换掉和谐掉显示文字的函数,发现待显示字串中有“[UNREGISTERED]”字样就把他删除了再显示
前两种途径难度都很大。那么祈祷一下 “[UNREGISTERED]” 是存在数据段或者是其他文件中的,不过显然作者不会这么弱的…… 于是就换掉显示文字的函数,用 file 命令发现 rainlendar 是动态链接的,那么这个成功的希望比较大。
Rainlendar 链接到了 libpango,那么几乎可以断定它是使用 Pango 绘制文字的,容易知道 Pango 绘制文字的函数是 pango_layout_set_text_orig
,它的签名是
void pango_layout_set_text (PangoLayout *layout, const char *text, int length); |
到这里就很接近成功啦 由于 Linux 支持 LD_PRELOAD,那么换掉一个库函数很简单:
#include <string.h> #include <stdlib.h> #include <dlfcn.h> #define UNREGISTERED "[UNREGISTERED] " static void *libpango; static void (*pango_layout_set_text_orig)(void *, const char *, int); __attribute__((__constructor__)) void pango_hook_init() { libpango = dlopen("libpango-1.0.so", RTLD_LOCAL | RTLD_LAZY); pango_layout_set_text_orig = dlsym(libpango, "pango_layout_set_text"); } void pango_layout_set_text(void *layout, const char *text, int length) { char *p = text ? strstr(text, UNREGISTERED) : 0; if (__builtin_expect((long)p, 0)) { int len = length >= 0 ? length : strlen(text); memmove(p, p + sizeof(UNREGISTERED) - 1, (len -= sizeof(UNREGISTERED) - 1) - (p - text) ); if (length >= 0) length = len; } pango_layout_set_text_orig(layout, text, length); } |
使用 gcc $^ -fPIC -shared -o libpango_hook.so -ldl
将上面的代码编译成动态链接库文件 libpango_hook.so,接着修改 /usr/bin/rainlendar,在运行 Rainlendar 之前,正确设置好 LD_PRELOAD,大概是这个样子:
#!/bin/dash RAINLENDAR_PATH='/opt/rainlendar2' export LD_PRELOAD="$RAINLENDAR_PATH/libpango_hook.so" exec $RAINLENDAR_PATH/rainlendar2 |
接着祈祷一下 Rainlendar 不是通过 dlopen 再 dlsym 的方式定位 pango_layout_set_text 这个函数的,那么事实证明它确实不是这样的
虽然中文字体不好看,但是“[UNREGISTERED]”不见了。
咦,沙发?
yyyyyyyyyyyyyyyyyyyyyyyyyyyym
呵呵,楼主牛人,我在win7上,不知道怎么去掉,共享一下改好的文件哈,谢谢.
lz再研究一下windows的?
@roy : @mars :
Windows 下没有 LD_PRELOAD。如果办到类似的事情有其他违法的途径会相对容易,这样的话不会公开写在这里…. -,- 见谅
Great! 解决了我的问题!谢谢!
To-do list中的[UNREGISTER]消失了,可是为什么EVENT list 标题中的又出来了?
@鸿剑青 : Rainlender 会截断过长的文字,也就是会出现 [UNREG… 或者是 …ISTER] 这样的情况,对他们分别作处理之后就很好了。
嗯,之前出现的状况砥确是你所描述的情况,应该正如你所分析的,启用了新版本,用一下,看看效果。非常感谢!
楼主高人! 看了你的文章,能看明白是什么,但是动手能力太差,可否提供win7下修改好的文件? 拜谢!
@胡 : 你没有看到上面的评论吗?这种方法对 Windows 不适用。
你的博客确实好,三天不来受不了!
感受学习的力量!
Thank you for sharing with us, I believe this website really stands out :D.
Wohh just what I was searching for, appreciate it for posting.